<?php
/**
 *  MyApp_Controller_Base.php
 *
 *  @author     TinhBV
 *  @package    Smscom
 *  @version
 */

define('BASE', dirname(dirname(__FILE__)));

$app = BASE . "/app";
$lib = BASE . "/lib";
$model = $app . "/model";
ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . implode(PATH_SEPARATOR, array(BASE, $app, $lib, $model)));


require_once 'Ethna/Ethna.php';
require_once 'MyApp_Error.php';
require_once 'MyApp_ActionClass.php';
require_once 'MyApp_ActionForm.php';
require_once 'MyApp_ViewClass.php';
require_once 'MyApp_Session.php';
require_once 'MyApp_ClassFactory.php';

require_once 'MyApp_Common.php';


/**
 *  Smscomアプリケーションのコントローラ定義
 *
 *  @author     {$author}
 *  @access     public
 *  @package    Smscom
 */
class MyApp_Controller_Base extends Ethna_Controller
{
    /**#@+
     *  @access private
     */

    /**
     *  @var    string  アプリケーションID
     */
    var $appid = 'MyApp';

    /**
     *  @var    array   forward定義
     */
    var $forward = array(
        /*
         *  TODO: ここにforward先を記述してください
         *
         *  記述例：
         *
         *  'index'         => array(
         *      'view_name' => 'MyApp_View_Index',
         *  ),
         */
    );

    /**
     *  @var    array   action定義
     */
    var $action = array(
        /*
         *  TODO: ここにaction定義を記述してください
         *
         *  記述例：
         *
         *  'index'     => array(),
         */
    );

    /**
     *  @var    array   soap action定義
     */
    var $soap_action = array(
        /*
         *  TODO: ここにSOAPアプリケーション用のaction定義を
         *  記述してください
         *  記述例：
         *
         *  'sample'            => array(),
         */
    );

    /**
     *  @var    array       アプリケーションディレクトリ
     */
    var $directory = array(
        'action'        => 'app/action',
        'action_cli'    => 'app/action_cli',
        'action_xmlrpc' => 'app/action_xmlrpc',
        'action_mobile' => 'app/action_mobile',
    	'action_sp' => 'app/action_sp',
        'app'           => 'app',
        'plugin'        => 'app/plugin',
        'bin'           => 'bin',
        'etc'           => 'etc',
        'filter'        => 'app/filter',
        'locale'        => 'locale',
        'log'           => 'log',
        'plugins'       => array(),
        'template'      => 'template',
        'template_mobile' => 'template_mobile',
    	'template_sp'	=> 'template_sp',
        'template_c'    => 'tmp/template_c',
        'tmp'           => 'tmp',
        'view'          => 'app/view',
        'view_mobile'   => 'app/view_mobile',
		'view_sp'		=> 'app/view_sp',
        'www'           => 'www',
        'model'         => 'app/model',
        'test'          => 'app/test',
        'mail'          => 'mail',
        'mail_mobile'   => 'mail_mobile',
        'schema'        => 'schema',
    );
    
    /**
     *  @var    array       DBアクセス定義
     */
    var $db = array(
        ''              => DB_TYPE_RW,
        'r'             => DB_TYPE_RO,
        's'             => DB_TYPE_MISC
    );

    /**
     *  @var    array       拡張子設定
     */
    var $ext = array(
        'php'           => 'php',
        'tpl'           => 'tpl',
    );

    /**
     *  @var    array   クラス定義
     */
    var $class = array(
        /*
         *  TODO: 設定クラス、ログクラス、SQLクラスをオーバーライド
         *  した場合は下記のクラス名を忘れずに変更してください
         */
        //'class'         => 'Ethna_ClassFactory',
        'class'         => 'MyApp_ClassFactory',
        'backend'       => 'Ethna_Backend',
        'config'        => 'Ethna_Config',
        //'db'            => 'Ethna_DB_PEAR',
        'db'            => 'MyApp_DB_PEAR',
        'error'         => 'Ethna_ActionError',
        'form'          => 'MyApp_ActionForm',
        'i18n'          => 'Ethna_I18N',
        'logger'        => 'Ethna_Logger',
        'plugin'        => 'Ethna_Plugin',
        //'session'       => 'Ethna_Session',
        'session'       => 'MyApp_Session',
        'sql'           => 'Ethna_AppSQL',
        'view'          => 'MyApp_ViewClass',
        'renderer'      => 'Ethna_Renderer_Smarty',
        'url_handler'   => 'MyApp_UrlHandler',
    );

    /**
     *  @var    array       検索対象となるプラグインのアプリケーションIDのリスト
     */
    var $plugin_search_appids = array(
        /*
         *  プラグイン検索時に検索対象となるアプリケーションIDのリストを記述します。
         *
         *  記述例：
         *  Common_Plugin_Foo_Bar のような命名のプラグインがアプリケーションの
         *  プラグインディレクトリに存在する場合、以下のように指定すると
         *  Common_Plugin_Foo_Bar, MyApp_Plugin_Foo_Bar, Ethna_Plugin_Foo_Bar
         *  の順にプラグインが検索されます。
         *
         *  'Common', 'Smscom', 'Ethna',
         */
        'Smscom', 'Ethna',
    );

    /**
     *  @var    array       フィルタ設定
     */
    var $filter = array(
        /*
         *  TODO: フィルタを利用する場合はここにそのプラグイン名を
         *  記述してください
         *  (クラス名を指定するとfilterディレクトリからフィルタクラス
         *  を読み込みます)
         *
         *  記述例：
         *
         *  'ExecutionTime',
         */
        'MyApp_Filter_Mobile',
        'MyApp_Filter_Common',
        'MyApp_Filter_Flash',
    );

    /**
     *  @var    array   smarty modifier定義
     */
    var $smarty_modifier_plugin = array(
        /*
         *  TODO: ここにユーザ定義のsmarty modifier一覧を記述してください
         *
         *  記述例：
         *
         *  'smarty_modifier_foo_bar',
         */
    );

    /**
     *  @var    array   smarty function定義
     */
    var $smarty_function_plugin = array(
        /*
         *  TODO: ここにユーザ定義のsmarty function一覧を記述してください
         *
         *  記述例：
         *
         *  'smarty_function_foo_bar',
         */
    );

    /**
     *  @var    array   smarty block定義
     */
    var $smarty_block_plugin = array(
        /*
         *  TODO: ここにユーザ定義のsmarty block一覧を記述してください
         *
         *  記述例：
         *
         *  'smarty_block_foo_bar',
         */
    );

    /**
     *  @var    array   smarty prefilter定義
     */
    var $smarty_prefilter_plugin = array(
        /*
         *  TODO: ここにユーザ定義のsmarty prefilter一覧を記述してください
         *
         *  記述例：
         *
         *  'smarty_prefilter_foo_bar',
         */
    );

    /**
     *  @var    array   smarty postfilter定義
     */
    var $smarty_postfilter_plugin = array(
        /*
         *  TODO: ここにユーザ定義のsmarty postfilter一覧を記述してください
         *
         *  記述例：
         *
         *  'smarty_postfilter_foo_bar',
         */
    );

    /**
     *  @var    array   smarty outputfilter定義
     */
    var $smarty_outputfilter_plugin = array(
        /*
         *  TODO: ここにユーザ定義のsmarty outputfilter一覧を記述してください
         *
         *  記述例：
         *
         *  'smarty_outputfilter_foo_bar',
         */
    );

    var $mobile_util;
    
    var $system_error;

    /**
     * device_type 端末タイプ
     * 0:PC 1:MB 2:SP
     */ 
    var $device_type;
    
    static $__DEVICE_TYPE_PC         = 0;
    static $__DEVICE_TYPE_MOBILE     = 1;
    static $__DEVICE_TYPE_SMARTPHONE = 2;
    
    function MyApp_Controller_Base($gateway = GATEWAY_WWW)
    {
    	
        parent::Ethna_Controller($gateway);
        $this->mobile_util = new Mobile_Util();
        $this->device_type = self::$__DEVICE_TYPE_PC;
        if(Mobile_Util::isMobile()){
        	$this->device_type = self::$__DEVICE_TYPE_MOBILE;
        }elseif(Mobile_Util::isSmartPhone()){
            //#58 Start Luvina Modify
            $pc = $_REQUEST['pc'];
            if($pc != "true") {
                $this->device_type = self::$__DEVICE_TYPE_SMARTPHONE;
            }
            //#58 Start Luvina Modify
        }
    }

    function setSystemErrorMessage($error)
    {
        $this->system_error = $error;
    }
    
    function getSystemErrorMessage()
    {
        return $this->system_error;
    }
    
    /**
     *  メールディレクトリ名を決定する
     *
     *  @access public
     *  @return string  メールテンプレートディレクトリ
     */
    function getMaildir($mobile=false)
    {
        $key = $mobile ? 'mail_mobile' : 'mail';
        $mail = $this->getDirectory($key);

        return $mail;
    }

    /**
     *  クライアントタイプ/言語からテンプレートディレクトリ名を決定する
     *
     *  @access public
     *  @return string  テンプレートディレクトリ
     */
    function getTemplatedir($device_type = null)
    {
        //$key = Mobile_Util::isMobile() ? 'template_mobile' : 'template';
        $key = 'template' . $this->_getDirSuffix($device_type);
        $template = $this->getDirectory($key);

        // 言語別ディレクトリ
        if (file_exists($template . '/' . $this->language)) {
            $template .= '/' . $this->language;
        }

        return $template;
    }

    /**
     *  アクションディレクトリ名を決定する
     *
     *  @access public
     *  @return string  アクションディレクトリ
     */
    function getActiondir($gateway = null,$device_type = null)
    {
        $key = 'action';
        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
        switch ($gateway) {
        case GATEWAY_WWW:
            //$key = Mobile_Util::isMobile() ? 'action_mobile' : 'action';
            $key = 'action' . $this->_getDirSuffix($device_type);
            break;
        case GATEWAY_CLI:
            $key = 'action_cli';
            break;
        case GATEWAY_XMLRPC:
            $key = 'action_xmlrpc';
            break;
        }

        return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
    }

    /**
     *  ビューディレクトリ名を決定する
     *
     *  @access public
     *  @return string  ビューディレクトリ
     */
    function getViewdir($device_type = null)
    {
        //$key = Mobile_Util::isMobile() ? 'view_mobile' : 'view';
        $key = 'view' . $this->_getDirSuffix($device_type);
        return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
    }

    /**
     *  Mobileセッション（非クッキー環境）におけるフォーム用のHiddenタグの取得
     *
     *  @access public
     *  @return string  セッション情報を埋め込んだHiddenタグ
     */
    function getSessionHiddenTag()
    {
        $s = '';
        if (Mobile_Util::isMobile() && session_id() != '') {
            $s = sprintf('<input type="hidden" name="%s" value="%s" />', htmlspecialchars(session_name(), ENT_QUOTES), htmlspecialchars(session_id(), ENT_QUOTES));
        }
        return $s;
    }

    /**
     *  アクション名を指定するクエリ/HTMLを生成する
     *
     *  @access public
     *  @param  string  $action action to request
     *  @param  string  $type   hidden, url...
     *  @todo   consider gateway
     */
    function getActionRequest($action, $type = "hidden")
    {
        $s = null;
        if ($type == "hidden") {
            $s = sprintf('<input type="hidden" name="action_%s" value="true" />', htmlspecialchars($action, ENT_QUOTES));
        } else if ($type == "url") {
            $s = sprintf('action_%s=true', urlencode($action));
        }
        return $s;
    }
    /**
     *  オーバーライド
     *  ディレクトリトラバーサル攻撃対策
     */
    function getDefaultViewPath($forward_name)
    {
        if(!(strpos($forward_name, 'http://'. SMSCOM_URL )===0      // 自サイトURL以外で始まる場合はリダイレクト
         ||  strpos($forward_name,'https://'. SMSCOM_URL )===0
         ||  preg_match('`^[a-z][-_a-z0-9]*$`i',$forward_name) )){       // viewへのフォワードは^[a-z][_-a-z0-9]*$ の場合のみ許可
            Ethna::raiseError('許可されていないforward_nameです。: \''. $forward_name .'\'', E_USER_ERROR);
            trigger_error('denied forward name : \''. $forward_name .'\'',	E_USER_ERROR);
            exit();
        }
        return parent::getDefaultViewPath($forward_name);
    }
    
    /**
     *  アクションスクリプトをインクルードする
     *
     *  ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
     *
     *  @access private
     *  @param  array   $action_obj     アクション定義
     *  @param  string  $action_name    アクション名
     */
    function _includeActionScript($action_obj, $action_name)
    {
    	$class_path = $form_path = null;
    
    	$action_dir = $this->getActiondir();
    
    	// class_path属性チェック
    	if (isset($action_obj['class_path'])) {
    		// フルパス指定サポート
    		$tmp_path = $action_obj['class_path'];
    		if (Ethna_Util::isAbsolute($tmp_path) == false) {
    			$tmp_path = $action_dir . $tmp_path;
    		}
    
    		if (file_exists($tmp_path) == false) {
    			$this->logger->log(LOG_WARNING, 'class_path file not found [%s] -> try default', $tmp_path);
    		} else {
    			include_once $tmp_path;
    			$class_path = $tmp_path;
    		}
    	}
    
    	// デフォルトチェック
    	if (is_null($class_path)) {
    		$class_path = $this->getDefaultActionPath($action_name);
    		if (file_exists($action_dir . $class_path)) {
    			include_once $action_dir . $class_path;
    		} else {
    			$this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path);
    			$class_path = null;
    		}
    	}
    
    	if(is_null($class_path) && $this->device_type == self::$__DEVICE_TYPE_SMARTPHONE){
    		$this->device_type = self::$__DEVICE_TYPE_PC;
    		$action_dir = $this->getActiondir();
    	
    		// class_path属性チェック
    		if (isset($action_obj['class_path'])) {
    			// フルパス指定サポート
    			$tmp_path = $action_obj['class_path'];
    			if (Ethna_Util::isAbsolute($tmp_path) == false) {
    				$tmp_path = $action_dir . $tmp_path;
    			}
    	
    			if (file_exists($tmp_path) == false) {
    				$this->logger->log(LOG_WARNING, 'class_path file not found [%s] -> try default', $tmp_path);
    			} else {
    				include_once $tmp_path;
    				$class_path = $tmp_path;
    			}
    		}
    	
    		// デフォルトチェック
    		if (is_null($class_path)) {
    			$class_path = $this->getDefaultActionPath($action_name);
    			if (file_exists($action_dir . $class_path)) {
    				include_once $action_dir . $class_path;
    			} else {
    				$this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path);
    				$class_path = null;
    			}
    		}
    	}
    	
    	// 全ファイルインクルード
    	if (is_null($class_path)) {
    		$this->_includeDirectory($this->getActiondir());
    		return;
    	}
    
    	// form_path属性チェック
    	if (isset($action_obj['form_path'])) {
    		// フルパス指定サポート
    		$tmp_path = $action_obj['form_path'];
    		if (Ethna_Util::isAbsolute($tmp_path) == false) {
    			$tmp_path = $action_dir . $tmp_path;
    		}
    
    		if ($tmp_path == $class_path) {
    			return;
    		}
    		if (file_exists($tmp_path) == false) {
    			$this->logger->log(LOG_WARNING, 'form_path file not found [%s] -> try default', $tmp_path);
    		} else {
    			include_once $tmp_path;
    			$form_path = $tmp_path;
    		}
    	}
    
    	// デフォルトチェック
    	if (is_null($form_path)) {
    		$form_path = $this->getDefaultFormPath($action_name);
    		if ($form_path == $class_path) {
    			return;
    		}
    		if (file_exists($action_dir . $form_path)) {
    			include_once $action_dir . $form_path;
    		} else {
    			$this->logger->log(LOG_DEBUG, 'default form file not found [%s] -> maybe falling back to default form class', $form_path);
    		}
    	}
    }
    
	/**
     *  各ディレクトリの接尾辞を取得する
     *  各ディレクトリへの振り分けの定義
     */
    function _getDirSuffix($device_type = null){
        $suffix = '';
        if(is_null($device_type)){
            $device_type = $this->device_type;
        }
        switch($device_type){
            case self::$__DEVICE_TYPE_MOBILE:
                $suffix = '_mobile';
                break;
            case self::$__DEVICE_TYPE_SMARTPHONE:
                $suffix = '_sp';
                break;
            case self::$__DEVICE_TYPE_PC:
            default:
                break;
        }
        return $suffix;
    }
    /**#@-*/
}